Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent Unnecessary Update Request in Facilities Section #8956

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from

Conversation

kihan2518B
Copy link

@kihan2518B kihan2518B commented Oct 28, 2024

Proposed Changes

image

  • Added isDirty state to the Form component
  • managing button disable state by isDirty state in Form component.
  • Utilizing Form component in BedCapacity and StaffCapacity .

@ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate bug / test a new feature.
  • Update product documentation.
  • Ensure that UI text is kept in I18n files.
  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews
  • Completion of QA

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new Form component to streamline form handling across various components.
    • Enhanced validation logic to check for negative values in specific fields.
    • Added dynamic button configurations to the form for improved user interaction.
  • Improvements

    • Simplified form submission and error management processes.
    • Updated button interactivity based on capacity constraints in the FacilityBedCapacity component.
    • Improved organization and clarity of form handling logic across multiple components.

These changes enhance user experience by providing a more intuitive and efficient interface for managing form data.

@kihan2518B kihan2518B requested a review from a team as a code owner October 28, 2024 18:06
Copy link

netlify bot commented Oct 28, 2024

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit 7ae6649
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/672ba2bd1fa1470008dfbd98
😎 Deploy Preview https://deploy-preview-8956--care-ohc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

src/components/Facility/BedCapacity.tsx Show resolved Hide resolved
src/components/Facility/BedCapacity.tsx Outdated Show resolved Hide resolved
src/components/Facility/StaffCapacity.tsx Outdated Show resolved Hide resolved
src/components/Facility/StaffCapacity.tsx Show resolved Hide resolved
src/components/Form/Form.tsx Outdated Show resolved Hide resolved
package-lock.json Outdated Show resolved Hide resolved
@Jacobjeevan
Copy link
Contributor

Jacobjeevan commented Oct 29, 2024

There's already another PR for the infinite load issues for Beds. In the future, make sure to get issue assigned or mention in the original thread before starting to work on an issue.

@kihan2518B
Copy link
Author

I had made those necessary changes.

package-lock.json Outdated Show resolved Hide resolved
src/components/Form/Form.tsx Outdated Show resolved Hide resolved
src/components/Facility/BedCapacity.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@Jacobjeevan Jacobjeevan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add package-lock back in (checked out from develop branch).

src/components/Form/Form.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@Jacobjeevan Jacobjeevan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

package-lock.json Outdated Show resolved Hide resolved
@@ -23,6 +23,7 @@ type Props<T extends FormDetails> = {
onDraftRestore?: (newState: FormState<T>) => void;
children: (props: FormContextValue<T>) => React.ReactNode;
hideRestoreDraft?: boolean;
showSaveAndAddMoreBtn?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the prefix show makes it read as expected type to be a boolean, but string is expected. This could be confusing.

How about a more generic solution that'd allow us to freely add any type of button and make the actual component that uses this component define what type of button to show specifically?

Suggested change
showSaveAndAddMoreBtn?: string;
additionalButtons?: { type: "submit" | "button"; label: string; id: string }[];

@@ -14,7 +14,7 @@ type Props<T extends FormDetails> = {
defaults: T;
asyncGetDefaults?: (() => Promise<T>) | false;
validate?: (form: T) => FormErrors<T>;
onSubmit: (form: T) => Promise<FormErrors<T> | void>;
onSubmit: (form: T, btnType?: string) => Promise<FormErrors<T> | void>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
onSubmit: (form: T, btnType?: string) => Promise<FormErrors<T> | void>;
onSubmit: (form: T, source?: string) => Promise<FormErrors<T> | void>;

src/components/Form/Form.tsx Outdated Show resolved Hide resolved
@@ -34,6 +35,8 @@ const Form = <T extends FormDetails>({
const [isLoading, setIsLoading] = useState(!!asyncGetDefaults);
const [state, dispatch] = useAutoSaveReducer<T>(formReducer, initial);

const [isDirty, setIsDirty] = useState(false); // Added isDirty state
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove obvious comments

Suggested change
const [isDirty, setIsDirty] = useState(false); // Added isDirty state
const [isDirty, setIsDirty] = useState(false);

if (valid) {
setIsLoading(true);
//Converting new data from string to Number
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//Converting new data from string to Number

@kihan2518B
Copy link
Author

Fix : Unnecessary Update Requests in Shifting and Resource Records #8982

@github-actions github-actions bot added the merge conflict pull requests with merge conflict label Nov 4, 2024
Copy link

github-actions bot commented Nov 4, 2024

👋 Hi, @kihan2518B,
Conflicts have been detected against the base branch. Please rebase your branch against the base branch.


This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there.

@kihan2518B
Copy link
Author

image

assigned_facility_type is required but there is no field to add it.

@github-actions github-actions bot removed the merge conflict pull requests with merge conflict label Nov 5, 2024
@kihan2518B
Copy link
Author

@rithviknishad can you review my changes?

onSubmit: (
form: T,
source?: string,
discharged?: boolean,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passing "discharged" in a generic reusable component is not ideal.

Suggested change
discharged?: boolean,

Copy link
Author

@kihan2518B kihan2518B Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I Thought it is necessary to keep it in Form component to use it in ShitDetailsUpdate Component

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't see any usages that is passing the third argument to this function when invoking. Can you point it out if present?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove it

name="status"
value={field("status").value}
options={resourceStatusOptions}
onChange={(e: any) => field("status").onChange(e)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any type not allowed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'ill remove it

<UserAutocomplete
label="Assigned To"
value={field("assigned_to_object").value}
onChange={(e: any) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove any type here too and all other places that you've added/modified

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

Comment on lines 153 to 162
if (btn.label) {
return (
<Submit
id={btn.id}
type={btn.type}
disabled={disabled || !isDirty}
label={btn.label}
/>
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. why have an if block checking if label is present? the type definition says it's not nullable.
  2. forgot to pass key ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did removed it.
I think it would give an additional check

Copy link

coderabbitai bot commented Nov 5, 2024

Walkthrough

The changes involve significant updates to several components related to form handling within the application. The BedCapacity, StaffCapacity, ResourceDetailsUpdate, and ShiftDetailsUpdate components now utilize a new Form component to streamline form management, validation, and submission processes. Additionally, the FacilityBedCapacity component introduces a disabled property for the ButtonV2 component to prevent adding more bed types when the capacity is reached. These modifications enhance the structure and clarity of the form handling logic across the components.

Changes

File Change Summary
src/components/Facility/BedCapacity.tsx Updated handleSubmit to accept a form parameter; integrated new Form component for field management.
src/components/Facility/FacilityBedCapacity.tsx Added disabled property to ButtonV2 to control button interactivity based on bed types count.
src/components/Facility/StaffCapacity.tsx Refactored form handling with new Form component; updated handleSubmit and validateData signatures.
src/components/Form/Form.tsx Updated Props type for onSubmit and added additionalButtons property; introduced isDirty state.
src/components/Resource/ResourceDetailsUpdate.tsx Replaced manual form handling with new Form component; updated validateForm to accept form parameter.
src/components/Shifting/ShiftDetailsUpdate.tsx Integrated new Form component; updated handleSubmit and validateForm signatures for improved handling.

Assessment against linked issues

Objective Addressed Explanation
Prevent submit button when form content is not changed (#8918)
Prevent adding more beds when all bed types are already selected (#8946)

🐇 In the fields where we play,
A new form leads the way!
No more clicks that lead to naught,
Changes made, or none, we thought!
With buttons bright and logic clear,
Our updates bring us cheer! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (12)
src/components/Facility/FacilityBedCapacity.tsx (3)

Line range hint 14-14: Consider adding proper TypeScript types for props.

Using any type for props reduces type safety and makes the code more prone to runtime errors.

Consider defining a proper interface:

interface FacilityBedCapacityProps {
  facilityId: string;
}

export const FacilityBedCapacity = (props: FacilityBedCapacityProps) => {

Line range hint 19-24: Add loading and error states for capacityQuery.

The component doesn't handle loading or error states for the capacity query, which could lead to poor user experience.

Consider adding loading and error handling:

if (capacityQuery.isLoading) {
  return <LoadingSpinner />;
}

if (capacityQuery.error) {
  return <ErrorMessage error={capacityQuery.error} />;
}

Line range hint 93-103: Consider adding a tooltip for disabled state.

When the button is disabled, users should understand why they can't add more bed types.

Add a tooltip to improve user experience:

 <ButtonV2
   id="facility-add-bedtype"
   className="w-full md:w-auto"
   onClick={() => setBedCapacityModalOpen(true)}
   disabled={BED_TYPES.length === capacityQuery.data?.count}
   authorizeFor={NonReadOnlyUsers}
+  title={BED_TYPES.length === capacityQuery.data?.count ? "All bed types have been added" : ""}
 >
src/components/Form/Form.tsx (2)

17-17: Consider using undefined instead of void in the union type.

The static analysis tool correctly flags that void in a union type can be confusing. Using undefined would be more appropriate here as it better represents the absence of a return value.

-  onSubmit: (form: T, source?: string) => Promise<FormErrors<T> | void>;
+  onSubmit: (form: T, source?: string) => Promise<FormErrors<T> | undefined>;
🧰 Tools
🪛 Biome

[error] 17-17: void is confusing inside a union type.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


80-96: Consider simplifying and improving the value comparison logic.

While the current implementation works, it could be made more robust and maintainable.

-    if (typeof props.defaults[name] == typeof value) {
-      setIsDirty(props.defaults[name] !== value);
-    } else {
-      setIsDirty(JSON.stringify(props.defaults[name]) !== value);
-    }
+    const defaultValue = props.defaults[name];
+    const isChanged = typeof value === 'object' && value !== null
+      ? JSON.stringify(defaultValue) !== JSON.stringify(value)
+      : defaultValue !== value;
+    setIsDirty(isChanged);
src/components/Facility/StaffCapacity.tsx (1)

34-42: Consider adding proper TypeScript types.

While the reducer implementation is good, it would benefit from proper TypeScript types instead of using any.

-const doctorCapacityReducer = (state = initialState, action: any) => {
+type DoctorCapacityAction = 
+  | { type: 'set_form'; form: typeof initForm }
+  | { type: 'set_error'; errors: typeof initForm }
+  | { type: 'set_field'; name: string; value: string; error?: string };
+
+const doctorCapacityReducer = (
+  state = initialState,
+  action: DoctorCapacityAction
+) => {
src/components/Facility/BedCapacity.tsx (2)

260-260: Enhance internationalization by translating the 'Bed Type' label

In the SelectFormField component, the label is set to "Bed Type". Consider using the t function to translate this label for internationalization support.

Apply this diff to use the translation function:

- label="Bed Type"
+ label={t("bed_type")}

264-289: Ensure all form labels are translated for consistency

The labels for form fields such as "Total Capacity" and "Currently Occupied" are hardcoded. To maintain consistency and support multiple languages, consider using the t function for these labels.

Update the labels as follows:

- label="Total Capacity"
+ label={t("total_capacity")}
...
- label="Currently Occupied"
+ label={t("currently_occupied")}
src/components/Resource/ResourceDetailsUpdate.tsx (2)

Line range hint 35-36: Add missing required fields to validation

The title and reason fields are essential for the resource request but are not included in the requiredFields object. As a result, they are not validated for emptiness, which may allow submission of incomplete forms.

Consider adding title and reason to the requiredFields to ensure they are validated properly:

 const requiredFields: any = {
   approving_facility_object: {
     errorText: "Resource approving facility can not be empty.",
   },
+  title: {
+    errorText: "Request title cannot be empty.",
+  },
+  reason: {
+    errorText: "Description of request cannot be empty.",
+  },
   assigned_facility_type: {
     errorText: "Please Select Facility Type",
   },
 };

85-85: Check for unnecessary state management

The assignedUserLoading state is obtained from useQuery, but there is also an isLoading state managed separately. Ensure that loading states are handled consistently to avoid confusion or redundant renders.

Consider consolidating loading states or clearly distinguishing their purposes.

src/components/Shifting/ShiftDetailsUpdate.tsx (2)

174-177: Unused parameter source in handleSubmit function

The source parameter in the handleSubmit function is not used within the function body. Consider removing it to clean up the code.

Apply this diff to remove the unused parameter:

 const handleSubmit = async (
     form: typeof initForm,
-    source?: string,
     discharged = false,
 ) => {

344-366: Simplify setSelected function in FacilitySelect

The setSelected function can be simplified by directly updating the shifting_approving_facility_object without the redundant approving_facility field, which may not be necessary.

Apply this diff to simplify the function:

 setSelected={(obj: any) => {
     field("shifting_approving_facility_object").onChange({
         name: "shifting_approving_facility_object",
         value: obj,
     });
-    field("approving_facility").onChange({
-        name: "approving_facility",
-        value: obj.id,
-    });
 }}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5877d9b and cbea55e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • src/components/Facility/BedCapacity.tsx (5 hunks)
  • src/components/Facility/FacilityBedCapacity.tsx (1 hunks)
  • src/components/Facility/StaffCapacity.tsx (3 hunks)
  • src/components/Form/Form.tsx (8 hunks)
  • src/components/Resource/ResourceDetailsUpdate.tsx (5 hunks)
  • src/components/Shifting/ShiftDetailsUpdate.tsx (4 hunks)
🧰 Additional context used
🪛 Biome
src/components/Form/Form.tsx

[error] 17-17: void is confusing inside a union type.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🔇 Additional comments (12)
src/components/Facility/FacilityBedCapacity.tsx (1)

95-95: ⚠️ Potential issue

Verify the disabled condition logic.

The disabled condition BED_TYPES.length === capacityQuery.data?.count might not accurately reflect the actual bed types in use. Consider using the results array length instead.

Apply this diff to fix the condition:

-disabled={BED_TYPES.length === capacityQuery.data?.count}
+disabled={BED_TYPES.length === capacityQuery.data?.results.length}

Let's verify the current implementation:

src/components/Form/Form.tsx (5)

26-30: LGTM! Well-typed additional buttons implementation.

The additionalButtons type definition is clear and type-safe, providing good flexibility for custom button configurations.


42-42: LGTM! Good implementation of form dirty state tracking.

The isDirty state effectively addresses the PR objective of preventing unnecessary update requests by tracking form modifications.


56-56: LGTM! Clean implementation of button source tracking and state reset.

The submit handler effectively:

  • Captures the source button ID in a type-safe manner
  • Resets the dirty state appropriately after submission

Also applies to: 70-72


115-115: LGTM! Appropriate reset of dirty state on draft restoration.

The isDirty state is correctly reset when a draft is restored, maintaining form state consistency.


142-158: LGTM! Well-implemented button rendering with consistent state management.

The button implementation:

  • Maintains consistent disabled state across all buttons
  • Properly identifies buttons with unique IDs
  • Cleanly renders additional buttons when provided
src/components/Facility/StaffCapacity.tsx (3)

5-7: LGTM! Good architectural improvement.

The integration of the Form component and related utilities provides better form state management and helps prevent unnecessary updates.


84-98: LGTM! Validation improvements implemented as requested.

The validation logic has been improved as per previous review feedback, with better readability using validForm.


146-197: Verify the "Save & Add More" functionality implementation.

The implementation looks good and follows the previous review feedback about keeping two buttons. Let's verify if this component is used consistently across the codebase.

✅ Verification successful

"Save & Add More" functionality is consistently implemented

The search results show that the "save-and-add-more" functionality is consistently implemented in both StaffCapacity.tsx and BedCapacity.tsx components, following the same pattern:

  • Both components handle the "save-and-add-more" source in their close handlers
  • Both use identical structure for the additionalButtons prop with the same button ID and type
  • The implementation in the review matches the pattern used elsewhere in the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent Form component usage with additionalButtons
# across the codebase

# Search for Form components with additionalButtons prop
rg -A 5 "additionalButtons=\[" --type typescript --type tsx

# Search for similar save-and-add-more patterns
ast-grep --pattern 'additionalButtons={[
  {
    id: "save-and-add-more",
    $$$
  }
]}'

Length of output: 188


Script:

#!/bin/bash
# Let's try a different approach to search for Form components with additional buttons

# Search for Form components with additionalButtons
rg -U "additionalButtons=\{.*\}" --type=tsx -A 5

# Also search for save-and-add-more pattern with more flexible matching
rg -U "save-and-add-more" --type=tsx -A 5

# Search for Form components to check overall usage pattern
rg "<Form\s+" --type=tsx -A 5

Length of output: 208


Script:

#!/bin/bash
# Let's try without specifying file types and use more general patterns

# Search for Form components with additionalButtons
rg -U "additionalButtons=\{.*\}"

# Search for save-and-add-more pattern
rg -U "save-and-add-more" -A 5

# Search for Form components usage
rg "<Form\s+" -A 5

Length of output: 2453

src/components/Facility/BedCapacity.tsx (1)

232-247: Conditional rendering of 'Save & Add More' button implemented correctly

The addition of the additionalButtons prop to the Form component and the conditional rendering of the "Save & Add More" button align with the previous suggestions and enhance the user experience.

src/components/Shifting/ShiftDetailsUpdate.tsx (2)

492-502: Handle missing breathlessness_level errors

Since breathlessness_level is required when wartimeShifting is enabled, ensure that error messages are displayed correctly when the field is not filled.

Run the following script to verify error handling:

#!/bin/bash
# Description: Check where 'breathlessness_level' errors are handled.

# Test: Search for usage of 'breathlessness_level' in error handling.
rg 'errors\[.*breathlessness_level.*\]'

452-462: Ensure patient_category has a default value

The patient_category field is required but may not have a default value in initForm, which could lead to form validation errors.

You can check if patient_category is set properly in initForm:

Number(state.form[field] < 0)
) {
validForm = false;
} else if (field === "currentOccupancy" && Number(form[field] < 0)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix logical error in number conversion within conditional checks

There is a logical error in the way Number() is used within the conditional statements. The expression Number(form[field] < 0) converts the boolean result of form[field] < 0 into a number (0 or 1), which is not the intended comparison.

To fix this issue, you should convert form[field] to a number before performing the comparison.

Apply this diff to correct the conditionals:

- } else if (field === "currentOccupancy" && Number(form[field] < 0)) {
+ } else if (field === "currentOccupancy" && Number(form[field]) < 0) {
...
- } else if (field === "totalCapacity" && Number(form[field] < 0)) {
+ } else if (field === "totalCapacity" && Number(form[field]) < 0) {

Also applies to: 126-126

Comment on lines 185 to 325
value: obj,
});
field("assigned_facility").onChange({
name: "assigned_facility",
value: obj.id,
});
}}
errors={state.errors.assigned_facility}
/>
</div>
<div>
<TextFormField
label="Required Quantity"
name="requested_quantity"
type="number"
value={field("requested_quantity").value}
onChange={(e) => field("requested_quantity").onChange(e)}
error={state.errors.requested_quantity}
/>
</div>
<div>
<TextFormField
name="assigned_quantity"
type="number"
label="Approved Quantity"
value={field("assigned_quantity").value}
onChange={(e) => field("assigned_quantity").onChange(e)}
disabled={state.form.status !== "PENDING"}
error={state.errors.assigned_quantity}
/>
</div>

<div className="md:col-span-2">
<TextAreaFormField
rows={5}
name="reason"
placeholder="Type your description here"
value={state.form.reason}
onChange={handleChange}
label="Description of request*"
error={state.errors.reason}
/>
</div>
<div className="md:col-span-2">
<TextFormField
name="title"
type="text"
label="Request Title*"
placeholder="Type your title here"
value={field("title").value}
onChange={(e) => field("title").onChange(e)}
error={state.errors.title}
/>
</div>

<div>
<RadioFormField
name="emergency"
onChange={handleChange}
label={"Is this an emergency?"}
options={[true, false]}
optionLabel={(o) => (o ? "Yes" : "No")}
optionValue={(o) => String(o)}
value={String(state.form.emergency)}
error={state.errors.emergency}
/>
</div>
<div className="md:col-span-2">
<TextAreaFormField
rows={5}
name="reason"
placeholder="Type your description here"
value={field("reason").value}
onChange={(e) => field("reason").onChange(e)}
label="Description of request*"
error={state.errors.reason}
/>
</div>

<div className="mt-4 flex flex-col justify-between gap-2 md:col-span-2 md:flex-row">
<Cancel variant="secondary" onClick={() => goBack()} />
<Submit onClick={handleSubmit} />
</div>
</div>
<div>
<RadioFormField
name="emergency"
onChange={(e) => field("emergency").onChange(e)}
label={"Is this an emergency?"}
options={[true, false]}
optionLabel={(o) => (o ? "Yes" : "No")}
optionValue={(o) => String(o)}
value={String(field("emergency").value)}
error={state.errors.emergency}
/>
</div>
</div>
)}
</Form>
</Card>
Copy link

@coderabbitai coderabbitai bot Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Include 'assigned_facility_type' field in the form

The assigned_facility_type field is marked as required in your validation logic, but it is not rendered in the form. This will cause the form to fail validation since users have no way to provide this information.

Please add a form field for assigned_facility_type to allow users to input this required information.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rithviknishad Am I supposed to add a field for "assigned_facility_type" as it was not present before.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines +229 to +236
field("approving_facility_object").onChange({
name: "approving_facility_object",
value: obj,
});
field("approving_facility").onChange({
name: "approving_facility",
value: obj.id,
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid using 'any' type for better type safety

The setSelected function receives obj: any, which undermines type safety. While previous comments have addressed the use of any, it's important to define a specific type for obj to improve maintainability and reduce potential runtime errors.

Consider defining an appropriate type for obj, such as FacilityModel or a relevant interface.

errors[field] = requiredFields[field].errorText;
isInvalidForm = true;
validForm = true;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix logical error in form validation

In the validateForm function, when a required field is missing, validForm should be set to false to indicate that the form is invalid. Currently, it's incorrectly set to true on line 94.

Apply this diff to correct the logic:

-        validForm = true;
+        validForm = false;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
validForm = true;
validForm = false;

Comment on lines +226 to +227
if (form.status !== form.initial_status) {
data["status"] = form.status;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add status field to initForm

The status field is used in the form but is not initialized in initForm. This might lead to undefined behavior when accessing form.status.

Apply this diff to add the status field:

 const initForm: any = {
     shifting_approving_facility_object: null,
+    status: "",
     assigned_facility_object: null,
     emergency: "false",

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +218 to +223
ambulance_driver_name: form.ambulance_driver_name,
ambulance_phone_number:
state.form.ambulance_phone_number === "+91"
form.ambulance_phone_number === "+91"
? ""
: parsePhoneNumber(state.form.ambulance_phone_number),
ambulance_number: state.form.ambulance_number,
: parsePhoneNumber(form.ambulance_phone_number),
ambulance_number: form.ambulance_number,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add breathlessness_level to initForm

The breathlessness_level field is used in the form but is not initialized in initForm. This could cause issues when accessing field("breathlessness_level").

Apply this diff to add the breathlessness_level field:

 const initForm: any = {
     shifting_approving_facility_object: null,
     assigned_facility_object: null,
+    breathlessness_level: "",
     emergency: "false",

Committable suggestion skipped: line range outside the PR's diff.


⚠️ Potential issue

Ensure default value handling for ambulance_phone_number

The logic for setting ambulance_phone_number might lead to incorrect handling of phone numbers that are exactly "+91". If "+91" is intended as a default or placeholder, consider improving the check to handle empty or invalid phone numbers more robustly.

Apply this diff to improve the validation:

 if (form.ambulance_phone_number === "+91" || !form.ambulance_phone_number.trim()) {
     ""
 } else {
     parsePhoneNumber(form.ambulance_phone_number)
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +344 to +366
<div>
<FieldLabel>
{t("name_of_shifting_approving_facility")}
</FieldLabel>
<FacilitySelect
multiple={false}
name="shifting_approving_facility"
facilityType={1300}
selected={field("shifting_approving_facility").value}
setSelected={(obj: any) => {
field("shifting_approving_facility_object").onChange({
name: "shifting_approving_facility",
value: obj,
});
field("approving_facility").onChange({
name: "approving_facility",
value: obj.id,
});
}}
errors={field("shifting_approving_facility_object").error}
/>
</div>
)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Field approving_facility is not defined in initForm

In the setSelected function for shifting_approving_facility, the code updates field("approving_facility"), but approving_facility is not initialized in initForm. This may lead to errors when the field is accessed or updated.

Apply this diff to add approving_facility to initForm:

 const initForm: any = {
     shifting_approving_facility_object: null,
+    approving_facility: "",
     assigned_facility_object: null,
     emergency: "false",

Committable suggestion skipped: line range outside the PR's diff.

@github-actions github-actions bot added the merge conflict pull requests with merge conflict label Nov 6, 2024
Copy link

github-actions bot commented Nov 6, 2024

👋 Hi, @kihan2518B,
Conflicts have been detected against the base branch. Please rebase your branch against the base branch.


This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there.

@github-actions github-actions bot added the Deploy-Failed Deplyment is not showing preview label Nov 6, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (9)
src/components/Form/Form.tsx (2)

27-27: Consider using undefined instead of void in union type.

The static analysis tool correctly flags that void in a union type can be confusing. Consider using undefined for better type safety.

- onSubmit: (form: T, source?: string) => Promise<FormErrors<T> | void>;
+ onSubmit: (form: T, source?: string) => Promise<FormErrors<T> | undefined>;
🧰 Tools
🪛 Biome

[error] 27-27: void is confusing inside a union type.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


36-40: Consider enhancing type safety for additionalButtons.

The additionalButtons type is well-structured, but could benefit from using a discriminated union for better type safety.

- additionalButtons?: {
-   type: "submit" | "button";
-   label: string;
-   id: string;
- }[];
+ additionalButtons?: Array<
+   | { type: "submit"; label: string; id: string }
+   | { type: "button"; label: string; id: string; onClick: () => void }
+ >;
src/components/Facility/StaffCapacity.tsx (4)

37-45: Add TypeScript types for reducer state and actions.

While the reducer implementation is clean, it would benefit from proper TypeScript types for better type safety and maintainability.

-const doctorCapacityReducer = (state = initialState, action: any) => {
+interface DoctorCapacityState {
+  form: typeof initForm;
+  errors: typeof initForm;
+}
+
+type DoctorCapacityAction =
+  | { type: 'set_form'; form: typeof initForm }
+  | { type: 'set_error'; errors: typeof initForm }
+  | { type: 'set_field'; name: string; value: string; error?: string };
+
+const doctorCapacityReducer = (
+  state = initialState,
+  action: DoctorCapacityAction
+): DoctorCapacityState => {

87-101: Enhance count field validation.

While the validation logic is good, consider adding additional validation for the count field:

  1. Ensure it's a valid integer
  2. Add a reasonable maximum limit
 } else if (field === "count" && form[field] < 0) {
   errors[field] = "Staff count cannot be negative";
   validForm = false;
+} else if (field === "count") {
+  const count = Number(form[field]);
+  if (!Number.isInteger(count)) {
+    errors[field] = "Staff count must be a whole number";
+    validForm = false;
+  } else if (count > 1000) { // adjust limit as needed
+    errors[field] = "Staff count exceeds maximum limit";
+    validForm = false;
+  }
 }

146-148: Enhance loading state UI.

Replace the basic loading text with a proper loading indicator for better user experience.

-<div>Loading...</div>
+<div className="flex items-center justify-center p-4">
+  <LoadingSpinner /> {/* assuming you have a loading spinner component */}
+  <span className="ml-2">Loading staff capacity details...</span>
+</div>

187-195: Add HTML5 validation attributes to count field.

Enhance the count field with proper HTML5 validation attributes for better user experience and client-side validation.

 <TextFormField
   required
   id="count"
   label="Count"
   name="count"
   type="number"
+  min="0"
+  max="1000"
+  step="1"
   value={field("count").value}
   onChange={(e: any) => field("count").onChange(e)}
 />
src/components/Facility/BedCapacity.tsx (3)

Line range hint 153-204: Add error handling for API requests

The submission logic lacks proper error handling for API failures. This could lead to the loading state being stuck if an error occurs.

Add try-catch block and error handling:

  const handleSubmit = async (form: typeof initForm, source?: string) => {
    const valid = validateData(form);
    if (valid) {
      setIsLoading(true);
+     try {
        const bodyData = {
          room_type: Number(form.bedType),
          total_capacity: Number(form.totalCapacity),
          current_capacity: Number(form.currentOccupancy),
        };
        const { data } = await request(
          id ? routes.updateCapacity : routes.createCapacity,
          {
            pathParams: { facilityId, ...(id ? { bed_id: id.toString() } : {}) },
            body: bodyData,
          },
        );
        if (data) {
          // ... existing success handling ...
        }
+     } catch (error) {
+       Notification.Error({
+         msg: "Failed to update bed capacity",
+       });
+     } finally {
        setIsLoading(false);
+     }
    }
  };

268-292: Enhance form field accessibility

The number input fields need additional ARIA labels and better validation messaging for screen readers.

Add accessibility improvements:

  <TextFormField
    className="w-full"
    id="total-capacity"
    name="totalCapacity"
    label="Total Capacity"
    required
    type="number"
+   aria-label="Enter total bed capacity"
+   aria-describedby="total-capacity-hint"
    value={field("totalCapacity").value}
    onChange={(e: any) => field("totalCapacity").onChange(e)}
    error={state.errors.totalCapacity}
    min={1}
  />
  <TextFormField
    className="w-full"
    id="currently-occupied"
    label="Currently Occupied"
    required
    name="currentOccupancy"
    type="number"
+   aria-label="Enter current occupancy"
+   aria-describedby="current-occupancy-hint"
    value={field("currentOccupancy").value}
    onChange={(e: any) => field("currentOccupancy").onChange(e)}
    error={state.errors.currentOccupancy}
    min={0}
    max={state.form.totalCapacity}
  />

146-151: Optimize last bed type check

The effect to check for the last bed type could be simplified and made more efficient.

Simplify the logic:

  useEffect(() => {
-   const lastBedType =
-     bedTypes.filter((i: OptionsType) => i.disabled).length ===
-     BED_TYPES.length - 1;
+   const disabledCount = bedTypes.reduce((count, type) => 
+     count + (type.disabled ? 1 : 0), 0);
+   const lastBedType = disabledCount === BED_TYPES.length - 1;
    setIsLastOptionType(lastBedType);
  }, [bedTypes]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between cbea55e and f8d191e.

📒 Files selected for processing (5)
  • cypress.config.ts (1 hunks)
  • src/components/Facility/BedCapacity.tsx (5 hunks)
  • src/components/Facility/FacilityBedCapacity.tsx (1 hunks)
  • src/components/Facility/StaffCapacity.tsx (3 hunks)
  • src/components/Form/Form.tsx (8 hunks)
✅ Files skipped from review due to trivial changes (1)
  • cypress.config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Facility/FacilityBedCapacity.tsx
🧰 Additional context used
🪛 Biome
src/components/Form/Form.tsx

[error] 27-27: void is confusing inside a union type.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🔇 Additional comments (6)
src/components/Form/Form.tsx (4)

52-52: LGTM: Clean implementation of form dirty state.

The isDirty state implementation follows React best practices and is properly initialized.


125-125: LGTM: Proper state reset on draft restoration.

Correctly resets the dirty state when a draft is restored.


152-168: LGTM: Clean implementation of dynamic button rendering.

The button rendering implementation is well-structured with:

  • Proper key usage in the map
  • Consistent disabled state handling
  • Clear button identification

66-66: Verify error handling across all form submissions.

The submit handler implementation looks good, with proper type-safe button identification and error handling. Let's verify the error handling implementation across the codebase.

Also applies to: 80-82

✅ Verification successful

Error handling implementation is consistent across form submissions

The verification of form submissions and error handling patterns across the codebase shows:

  • All form submissions properly handle errors through try-catch blocks or response status checks
  • Error states are managed consistently using state hooks (setError/setErrors)
  • Common error handling patterns found in:
    • Form submissions (CreatePrescriptionForm, EditPrescriptionForm)
    • Authentication flows (Login, ResetPassword)
    • Resource management (ResourceCommentSection, ShiftingCommentsSection)
    • Asset management (ConfigureCamera)

The buttonId extraction and error handling in the reviewed code aligns with the codebase's established patterns for form submission handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check error handling patterns in form submissions
# Look for consistent error handling patterns in form submission handlers

# Search for onSubmit implementations
rg -A 5 "onSubmit.*=.*async.*=>" --type typescript

# Search for form error handling patterns
rg -A 5 "FormErrors.*void" --type typescript

Length of output: 169


Script:

#!/bin/bash
# Search for form submission handlers and error handling patterns
rg -A 5 "onSubmit.*=.*async.*=>"
rg -A 5 "catch.*Error"

# Look for form-related error state management
rg -A 3 "setError|setFormError"

# Search for form submission implementations
ast-grep --pattern 'const $_ = async ($event: $_) => { $$$  }'

Length of output: 16650

src/components/Facility/StaffCapacity.tsx (1)

10-16: LGTM! Imports are well-organized.

The new imports for Form components and notifications are appropriate for the component's functionality.

src/components/Facility/BedCapacity.tsx (1)

117-132: ⚠️ Potential issue

Fix number conversion logic in validation checks

The number conversion syntax is incorrect in multiple places. The current implementation converts the result of the comparison instead of the form value.

Apply this diff to fix the number conversions:

- } else if (field === "currentOccupancy" && Number(form[field] < 0)) {
+ } else if (field === "currentOccupancy" && Number(form[field]) < 0) {
  errors[field] = "Occupied cannot be negative";
  validForm = false;
} else if (
  field === "currentOccupancy" &&
  Number(form[field]) > Number(form.totalCapacity)
) {
  errors[field] = "Occupied must be less than or equal to total capacity";
  validForm = false;
}
- if (field === "totalCapacity" && Number(form[field]) === 0) {
+ if (field === "totalCapacity" && Number(form[field]) <= 0) {
  errors[field] = "Total capacity cannot be 0";
  validForm = false;
- } else if (field === "totalCapacity" && Number(form[field] < 0)) {
-   errors[field] = "Total capacity cannot be negative";
-   validForm = false;
}

Likely invalid or redundant comment.

Comment on lines +90 to +106
const handleFieldChange = (
{ name, value }: FieldChangeEvent<T[keyof T]>,
validate?: FieldValidator<T[keyof T]>,
) => {
dispatch({
type: "set_field",
name,
value,
error: validate?.(value),
});

if (typeof props.defaults[name] == typeof value) {
setIsDirty(props.defaults[name] !== value);
} else {
setIsDirty(JSON.stringify(props.defaults[name]) !== value);
}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider simplifying the value comparison logic.

The current implementation has separate paths for different types which could be simplified and made more robust.

- if (typeof props.defaults[name] == typeof value) {
-   setIsDirty(props.defaults[name] !== value);
- } else {
-   setIsDirty(JSON.stringify(props.defaults[name]) !== value);
- }
+ const defaultValue = props.defaults[name];
+ const isEqual = typeof defaultValue === 'object' && defaultValue !== null
+   ? JSON.stringify(defaultValue) === JSON.stringify(value)
+   : defaultValue === value;
+ setIsDirty(!isEqual);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleFieldChange = (
{ name, value }: FieldChangeEvent<T[keyof T]>,
validate?: FieldValidator<T[keyof T]>,
) => {
dispatch({
type: "set_field",
name,
value,
error: validate?.(value),
});
if (typeof props.defaults[name] == typeof value) {
setIsDirty(props.defaults[name] !== value);
} else {
setIsDirty(JSON.stringify(props.defaults[name]) !== value);
}
};
const handleFieldChange = (
{ name, value }: FieldChangeEvent<T[keyof T]>,
validate?: FieldValidator<T[keyof T]>,
) => {
dispatch({
type: "set_field",
name,
value,
error: validate?.(value),
});
const defaultValue = props.defaults[name];
const isEqual = typeof defaultValue === 'object' && defaultValue !== null
? JSON.stringify(defaultValue) === JSON.stringify(value)
: defaultValue === value;
setIsDirty(!isEqual);
};

Comment on lines +115 to +141
const handleSubmit = async (form: typeof initForm, source?: string) => {
if (!validateData(form)) return;
setIsLoading(true);
const data = {
area: Number(form.area),
count: Number(form.count),
};
const { res } = await (id
? request(routes.updateDoctor, {
pathParams: { facilityId, id: `${id}` },
body: data,
})
: request(routes.createDoctor, {
pathParams: { facilityId },
body: data,
}));
setIsLoading(false);
if (res?.ok) {
specializationsQuery.refetch();
Notification.Success({
msg: id
? "Staff count updated successfully"
: "Staff count added successfully",
});
handleUpdate();

if (submitBtnID === "save-and-exit") handleClose();
}
if (source !== "save-and-add-more") handleClose();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix loading state management in error scenarios.

The loading state is only reset on successful API response. This could lead to a stuck loading state if the API request fails.

 const handleSubmit = async (form: typeof initForm, source?: string) => {
   if (!validateData(form)) return;
   setIsLoading(true);
   const data = {
     area: Number(form.area),
     count: Number(form.count),
   };
-  const { res } = await (id
-    ? request(routes.updateDoctor, {
-        pathParams: { facilityId, id: `${id}` },
-        body: data,
-      })
-    : request(routes.createDoctor, {
-        pathParams: { facilityId },
-        body: data,
-      }));
-  setIsLoading(false);
-  if (res?.ok) {
-    specializationsQuery.refetch();
-    Notification.Success({
-      msg: id
-        ? "Staff count updated successfully"
-        : "Staff count added successfully",
-    });
-    handleUpdate();
+  try {
+    const { res } = await (id
+      ? request(routes.updateDoctor, {
+          pathParams: { facilityId, id: `${id}` },
+          body: data,
+        })
+      : request(routes.createDoctor, {
+          pathParams: { facilityId },
+          body: data,
+        }));
+    if (res?.ok) {
+      specializationsQuery.refetch();
+      Notification.Success({
+        msg: id
+          ? "Staff count updated successfully"
+          : "Staff count added successfully",
+      });
+      handleUpdate();
+      if (source !== "save-and-add-more") handleClose();
+    }
+  } catch (error) {
+    Notification.Error({
+      msg: "Failed to update staff capacity"
+    });
+  } finally {
+    setIsLoading(false);
   }
-  if (source !== "save-and-add-more") handleClose();
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleSubmit = async (form: typeof initForm, source?: string) => {
if (!validateData(form)) return;
setIsLoading(true);
const data = {
area: Number(form.area),
count: Number(form.count),
};
const { res } = await (id
? request(routes.updateDoctor, {
pathParams: { facilityId, id: `${id}` },
body: data,
})
: request(routes.createDoctor, {
pathParams: { facilityId },
body: data,
}));
setIsLoading(false);
if (res?.ok) {
specializationsQuery.refetch();
Notification.Success({
msg: id
? "Staff count updated successfully"
: "Staff count added successfully",
});
handleUpdate();
if (submitBtnID === "save-and-exit") handleClose();
}
if (source !== "save-and-add-more") handleClose();
const handleSubmit = async (form: typeof initForm, source?: string) => {
if (!validateData(form)) return;
setIsLoading(true);
const data = {
area: Number(form.area),
count: Number(form.count),
};
try {
const { res } = await (id
? request(routes.updateDoctor, {
pathParams: { facilityId, id: `${id}` },
body: data,
})
: request(routes.createDoctor, {
pathParams: { facilityId },
body: data,
}));
if (res?.ok) {
specializationsQuery.refetch();
Notification.Success({
msg: id
? "Staff count updated successfully"
: "Staff count added successfully",
});
handleUpdate();
if (source !== "save-and-add-more") handleClose();
}
} catch (error) {
Notification.Error({
msg: "Failed to update staff capacity"
});
} finally {
setIsLoading(false);
}
};

@rithviknishad rithviknishad removed the Deploy-Failed Deplyment is not showing preview label Nov 6, 2024
@github-actions github-actions bot removed the merge conflict pull requests with merge conflict label Nov 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants